﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD.Core {
    /// <summary>
    /// リソース キャッシュをあらわす構造体
    /// </summary>
    /// <remarks>
    /// リソースとは、キーとなるオブジェクトと、そのオブジェクトに固有な値のペアです。
    /// オブジェクトへの参照は弱い参照 <see cref="WeakReference"/> によって行われるので
    /// リソース以外の参照が全て消えるとそのオブジェクトはGCによって削除・回収され、
    /// <see cref="Object"/> は <c>null</c> を返します。
    /// 保存されていたキーの型は <see cref="ObjectType"/> でいつでも取得可能です。
    /// この構造体はOpenGLの非マネージド リソースを管理するのに使用されます。
    /// </remarks>
    /// <typeparam name="T">リソースとして保存する値の型</typeparam>
    /// <seealso cref="CacheArray"/>
    internal struct Cache<T> where T : struct {

        #region Field
        WeakReference weak;
        T value;
        Type objectType;
        #endregion

        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <param name="key">キーとなる任意のオブジェクト</param>
        /// <param name="value">値</param>
        public Cache (Object key, T value) : this() {
            this.weak = new WeakReference (key);
            this.value = value;
            this.objectType = key.GetType ();
        }

        
        /// <summary>
        /// キー オブジェクト
        /// </summary>
        /// <remarks>
        /// このリソースのキーとなるオブジェクトです。
        /// このリソース以外からの参照が無くなった場合、キーオブジェクトはGCによって回収・無効化され、
        /// <c>null</c> が返ります。
        /// キー オブジェクトの有効無効は <see cref="IsValid"/> プロパティで判定可能です。
        /// </remarks>
        /// <seealso cref="IsValid"/>
        public Object Object { 
            get { return (Object)weak.Target;}
        }

        /// <summary>
        /// キーに結びつけれた値
        /// </summary>
        /// <remarks>
        /// このリソースのキーに結びつけれた値です。
        /// </remarks>
        public T Value {
            get { return value; }
        }

        /// <summary>
        /// キー オブジェクトの型
        /// </summary>
        /// <remarks>
        /// キー オブジェクト <see cref="Object"/> の型です。
        /// このプロパティはキー オブジェクトが解放された後も有効です。
        /// </remarks>
        public Type ObjectType {
            get { return objectType; }
        }


        /// <summary>
        /// 有効無効フラグ
        /// </summary>
        /// <remarks>
        /// このリソースの参照するオブジェクトが有効か、無効化されているかを判定します。
        /// キー オブジェクト <see cref="Object"/> がGCに回収されていなければ <c>true</c>,
        /// 回収済みなら <c>false</c> を返します。
        /// </remarks>
        public bool IsValid {
            get { return weak.IsAlive; }
        }

        /// <inheritdoc/>
        public override string ToString () {
            var name = (Object == null) ? "null" : Object.GetType ().Name;
            return string.Format("Resource: Key={0}, Value={1}", name, Value);
        }
    }
}
